package cn.kepu.elearning.controller;

import cn.kepu.elearning.common.Constants;
import cn.kepu.elearning.common.JsonResult;
import cn.kepu.elearning.common.ResultCode;
import cn.kepu.elearning.dto.UpdateByQueryDTO;
import cn.kepu.elearning.dto.match.*;
import cn.kepu.elearning.mapper.AllMapper;
import cn.kepu.elearning.util.ESUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 提供主服务操作es的接口
 *
 * @author Endy
 * @create 2019-12-03 下午7:52
 **/
@RestController
@RequestMapping("/es")
@Slf4j
public class ESController {

    @Autowired
    private AllMapper allMapper;

    @Value("${es.index}")
    private String index;

    @Value("${es.course.fields}")
    private String courseFields;
    @Value("${es.news.fields}")
    private String newsFields;
    @Value("${es.notice.fields}")
    private String noticeFields;
    @Value("${es.teacher.fields}")
    private String teacherFields;
    @Value("${es.train.fields}")
    private String trainFields;
    @Value("${es.series.fields}")
    private String seriesFields;

    /**
     * 搜索课程列表
     *
     * @param dto 参数dto
     * @return 课程列表
     */
    @PostMapping("/matchQueryCourse")
    public JsonResult matchQueryCourse(@RequestBody MatchQueryCourseDTO dto) {
        log.info("/matchQueryCourse的参数为【{}】", dto.toString());

        dto.setFieldNames(courseFields.split(","));
        Map<String, Object> result = ESUtil.matchQuery(index, dto.convert());
        return new JsonResult(ResultCode.SUCCESS, "", result);
    }

    /**
     * 获取课程本院和非本院的数量
     *
     * @param dto 参数dto
     * @return 本院和非本院的数量
     */
    @PostMapping("/countCourse")
    public JsonResult countCourse(@RequestBody MatchQueryCourseDTO dto) {
        log.info("/countCourse的参数为【{}】", dto.toString());
        if (dto.getSearchType() == null) {
            log.error("searchType不存在");
            return new JsonResult(ResultCode.PARAMS_ERROR, "searchType不存在");
        }
        dto.setFieldNames(courseFields.split(","));
        Map<String, Object> result = new HashMap<>();

        if (2 == dto.getSearchType()) {
            // 从参数传过来的课程形式
            String classficationFromParam = dto.getClassfication();
            // 从参数传过来的课程类型
            String fullPathFromParam = dto.getFullPath();
            // 从参数传过来的登录人的所属平台id
            String tenantId = dto.getTenantId();
            // 先将参数置空，获取到所有课程形式的数量以后，再将参数还原
            dto.setClassfication(null);
            dto.setFullPath(null);
            dto.setTenantId(null);

            List<Map<String, Object>> classfication = ESUtil.queryByType(index, Constants.Type.CLASSFICATION);
            // List<Map<String, Object>> classfication = allMapper.selectClassfication();
            List<Map<String, Object>> classficationCount = new ArrayList<>(classfication.size());
            Map<String, Object> m;
            for (Map<String, Object> map : classfication) {
                String code = map.get("code").toString();
                String name = map.get("name").toString();
                dto.setClassfication(code);
                m = new HashMap<>(3);
                m.put("code", code);
                m.put("name", name);
                m.put("count", ESUtil.count(index, dto.convert()));
                classficationCount.add(m);
            }
            long allCount = classficationCount.stream().mapToLong(map -> Long.parseLong(map.get("count").toString())).sum();
            m = new HashMap<>(3);
            m.put("code", 0);
            m.put("name", "全部");
            m.put("count", allCount);
            classficationCount.add(m);
            List<Map<String, Object>> sortedList = classficationCount.stream()
                    .sorted(Comparator.comparingInt(map -> Integer.parseInt(map.get("code").toString())))
                    .collect(Collectors.toList());
            result.put("classfication", sortedList);

            // 还原参数
            dto.setClassfication(classficationFromParam);
            dto.setFullPath(fullPathFromParam);
            dto.setTenantId(tenantId);
        }

        long thisCount = 0;
        if (StringUtils.isNotBlank(dto.getTenantId())) {
            dto.setIfTenantId("2701");
            thisCount = ESUtil.count(index, dto.convert());
        }
        dto.setIfTenantId("2702");
        long otherCount = ESUtil.count(index, dto.convert());
        result.put("thisCount", thisCount);
        result.put("otherCount", otherCount);
        return new JsonResult(ResultCode.SUCCESS, "", result);
    }

    @PostMapping("/matchQueryNews")
    public JsonResult matchQueryNews(@RequestBody MatchQueryNewsDTO dto) {
        log.info("/matchQueryNews的参数为【{}】", dto.toString());

        dto.setFieldNames(newsFields.split(","));
        Map<String, Object> result = ESUtil.matchQuery(index, dto.convert());
        return new JsonResult(ResultCode.SUCCESS, "", result);
    }

    /**
     * 获取新闻本院和非本院的数量
     *
     * @param dto 参数dto
     * @return 本院和非本院的数量
     */
    @PostMapping("/countNews")
    public JsonResult countNews(@RequestBody MatchQueryNewsDTO dto) {
        log.info("/countNews的参数为【{}】", dto.toString());

        dto.setFieldNames(newsFields.split(","));
        long thisCount = 0;
        if (StringUtils.isNotBlank(dto.getTenantId())) {
            dto.setIfTenantId("2701");
            thisCount = ESUtil.count(index, dto.convert());
        }
        dto.setIfTenantId("2702");
        long otherCount = ESUtil.count(index, dto.convert());
        Map<String, Object> result = new HashMap<>(2);
        result.put("thisCount", thisCount);
        result.put("otherCount", otherCount);
        return new JsonResult(ResultCode.SUCCESS, "", result);
    }

    @PostMapping("/matchQueryNotice")
    public JsonResult matchQueryNotice(@RequestBody MatchQueryNoticeDTO dto) {
        log.info("/matchQueryNotice的参数为【{}】", dto.toString());

        dto.setFieldNames(noticeFields.split(","));
        Map<String, Object> result = ESUtil.matchQuery(index, dto.convert());
        return new JsonResult(ResultCode.SUCCESS, "", result);
    }

    /**
     * 获取通知本院和非本院的数量
     *
     * @param dto 参数dto
     * @return 本院和非本院的数量
     */
    @PostMapping("/countNotice")
    public JsonResult countNotice(@RequestBody MatchQueryNoticeDTO dto) {
        log.info("/countNotice的参数为【{}】", dto.toString());

        dto.setFieldNames(noticeFields.split(","));
        long thisCount = 0;
        if (StringUtils.isNotBlank(dto.getTenantId())) {
            dto.setIfTenantId("2701");
            thisCount = ESUtil.count(index, dto.convert());
        }
        dto.setIfTenantId("2702");
        long otherCount = ESUtil.count(index, dto.convert());
        Map<String, Object> result = new HashMap<>(2);
        result.put("thisCount", thisCount);
        result.put("otherCount", otherCount);
        return new JsonResult(ResultCode.SUCCESS, "", result);
    }

    @PostMapping("/matchQueryTeacher")
    public JsonResult matchQueryTeacher(@RequestBody MatchQueryTeacherDTO dto) {
        log.info("/matchQueryTeacher的参数为【{}】", dto.toString());

        dto.setFieldNames(teacherFields.split(","));
        Map<String, Object> result = ESUtil.matchQuery(index, dto.convert());
        return new JsonResult(ResultCode.SUCCESS, "", result);
    }

    /**
     * 获取讲师本院和非本院的数量
     *
     * @param dto 参数dto
     * @return 本院和非本院的数量
     */
    @PostMapping("/countTeacher")
    public JsonResult countTeacher(@RequestBody MatchQueryTeacherDTO dto) {
        log.info("/countTeacher的参数为【{}】", dto.toString());

        if (dto.getSearchType() == null) {
            log.error("searchType不存在");
            return new JsonResult(ResultCode.PARAMS_ERROR, "searchType不存在");
        }
        dto.setFieldNames(teacherFields.split(","));
        Map<String, Object> result = new HashMap<>();

        if (2 == dto.getSearchType()) {
            // 从参数传过来的讲师领域
            String expertAreaIdFromParam = dto.getExpertAreaId();
            // 从参数传过来的登录人的所属平台id
            String tenantId = dto.getTenantId();
            // 先将参数置空，获取到所有讲师领域的数量以后，再将参数还原
            dto.setExpertAreaId(null);
            dto.setTenantId(null);

            List<Map<String, Object>> expertArea = ESUtil.queryByType(index, Constants.Type.EXPERT_AREA);
            // List<Map<String, Object>> expertArea = allMapper.selectExpertArea();
            List<Map<String, Object>> expertAreaCount = new ArrayList<>(expertArea.size());
            Map<String, Object> m;
            for (Map<String, Object> map : expertArea) {
                String CourseType_ID = map.get("CourseType_ID").toString();
                String courseTypeName = map.get("courseTypeName").toString();
                dto.setExpertAreaId(CourseType_ID);
                m = new HashMap<>(3);
                m.put("code", CourseType_ID);
                m.put("name", courseTypeName);
                m.put("count", ESUtil.count(index, dto.convert()));
                expertAreaCount.add(m);
            }
            long allCount = expertAreaCount.stream().mapToLong(map -> Long.parseLong(map.get("count").toString())).sum();
            m = new HashMap<>(3);
            m.put("code", 0);
            m.put("name", "全部");
            m.put("count", allCount);
            expertAreaCount.add(m);
            List<Map<String, Object>> sortedList = expertAreaCount.stream()
                    .sorted(Comparator.comparingInt(map -> Integer.parseInt(map.get("code").toString())))
                    .collect(Collectors.toList());
            result.put("expertArea", sortedList);

            // 还原参数
            dto.setExpertAreaId(expertAreaIdFromParam);
            dto.setTenantId(tenantId);
        }

        long thisCount = 0;
        if (StringUtils.isNotBlank(dto.getTenantId())) {
            dto.setIfTenantId("2701");
            thisCount = ESUtil.count(index, dto.convert());
        }
        dto.setIfTenantId("2702");
        long otherCount = ESUtil.count(index, dto.convert());
        result.put("thisCount", thisCount);
        result.put("otherCount", otherCount);
        return new JsonResult(ResultCode.SUCCESS, "", result);
    }

    @PostMapping("/matchQueryTrain")
    public JsonResult matchQueryTrain(@RequestBody MatchQueryTrainDTO dto) {
        log.info("/matchQueryTrain的参数为【{}】", dto.toString());

        dto.setFieldNames(trainFields.split(","));
        Map<String, Object> result = ESUtil.matchQuery(index, dto.convert());
        return new JsonResult(ResultCode.SUCCESS, "", result);
    }

    /**
     * 获取培训本院和非本院的数量
     *
     * @param dto 参数dto
     * @return 本院和非本院的数量
     */
    @PostMapping("/countTrain")
    public JsonResult countTrain(@RequestBody MatchQueryTrainDTO dto) {
        log.info("/countTrain的参数为【{}】", dto.toString());

        if (dto.getSearchType() == null) {
            log.error("searchType不存在");
            return new JsonResult(ResultCode.PARAMS_ERROR, "searchType不存在");
        }
        dto.setFieldNames(trainFields.split(","));
        Map<String, Object> result = new HashMap<>();

        if (2 == dto.getSearchType()) {
            // 从参数传过来的培训形式
            String trainTypeIDFromParam = dto.getTrainTypeID();
            // 从参数传过来的登录人的所属平台id
            String tenantId = dto.getTenantId();
            // 先将参数置空，获取到所有课程形式的数量以后，再将参数还原
            dto.setTrainTypeID(null);
            dto.setTenantId(null);

            List<Map<String, Object>> trainType = ESUtil.queryByType(index, Constants.Type.TRAIN_TYPE);
            // List<Map<String, Object>> trainType = allMapper.selectTrainType();
            List<Map<String, Object>> trainTypeCount = new ArrayList<>(trainType.size());
            Map<String, Object> m;
            for (Map<String, Object> map : trainType) {
                String code = map.get("code").toString();
                String name = map.get("name").toString();
                dto.setTrainTypeID(code);
                m = new HashMap<>(3);
                m.put("code", code);
                m.put("name", name);
                m.put("count", ESUtil.count(index, dto.convert()));
                trainTypeCount.add(m);
            }
            long allCount = trainTypeCount.stream().mapToLong(map -> Long.parseLong(map.get("count").toString())).sum();
            m = new HashMap<>(3);
            m.put("code", 0);
            m.put("name", "全部");
            m.put("count", allCount);
            trainTypeCount.add(m);
            List<Map<String, Object>> sortedList = trainTypeCount.stream()
                    .sorted(Comparator.comparingInt(map -> Integer.parseInt(map.get("code").toString())))
                    .collect(Collectors.toList());
            result.put("trainType", sortedList);

            dto.setItemType("1");
            long fineCount = ESUtil.count(index, dto.convert());
            result.put("fineCount", fineCount);
            dto.setItemType("2");
            long generalSelfCount = ESUtil.count(index, dto.convert());
            result.put("generalSelfCount", generalSelfCount);
            dto.setItemType("3");
            long generalCount = ESUtil.count(index, dto.convert());
            result.put("generalCount", generalCount);
            dto.setItemType(null);
            // 还原参数
            dto.setTrainTypeID(trainTypeIDFromParam);
            dto.setTenantId(tenantId);
        }

        long thisCount = 0;
        if (StringUtils.isNotBlank(dto.getTenantId())) {
            dto.setIfTenantId("2701");
            thisCount = ESUtil.count(index, dto.convert());
        }
        dto.setIfTenantId("2702");
        long otherCount = ESUtil.count(index, dto.convert());
        result.put("thisCount", thisCount);
        result.put("otherCount", otherCount);
        return new JsonResult(ResultCode.SUCCESS, "", result);
    }

    /**
     * 搜索系列专题列表
     *
     * @param dto 参数dto
     * @return 系列专题列表
     */
    @PostMapping("/matchQuerySeries")
    public JsonResult matchQuerySeries(@RequestBody MatchQuerySeriesDTO dto) {
        log.info("/matchQuerySeries的参数为【{}】", dto.toString());

        dto.setFieldNames(seriesFields.split(","));
        Map<String, Object> result = ESUtil.matchQuery(index, dto.convert());
        return new JsonResult(ResultCode.SUCCESS, "", result);
    }

    /**
     * 搜索系列专题本院和非本院的数量
     *
     * @param dto 参数dto
     * @return 本院和非本院的数量
     */
    @PostMapping("/countSeries")
    public JsonResult countSeries(@RequestBody MatchQuerySeriesDTO dto) {
        log.info("/countSeries的参数为【{}】", dto.toString());

        dto.setFieldNames(seriesFields.split(","));
        long thisCount = 0;
        if (StringUtils.isNotBlank(dto.getTenantId())) {
            dto.setIfTenantId("2701");
            thisCount = ESUtil.count(index, dto.convert());
        }
        dto.setIfTenantId("2702");
        long otherCount = ESUtil.count(index, dto.convert());
        Map<String, Object> result = new HashMap<>(2);
        result.put("thisCount", thisCount);
        result.put("otherCount", otherCount);
        return new JsonResult(ResultCode.SUCCESS, "", result);
    }


    /**
     * 搜索智能提示接口
     *
     * @param types      要查询的type，多个type之间用英文的 , 分割
     * @param filterText 输入的信息
     * @return 查询结果，只返回10条
     */
    @GetMapping("/querySuggestion")
    public JsonResult querySuggestion(@RequestParam(value = "types", required = false) String types,
                                      @RequestParam("filterText") String filterText) {
        Map<String, Object> map = new HashMap<>();
        map.put("result", null);
        if (StringUtils.isBlank(filterText)) {
            return new JsonResult(ResultCode.SUCCESS, "", map);
        }
        map = ESUtil.querySuggestion(index, types, filterText);
        return new JsonResult(ResultCode.SUCCESS, "", map);
    }

    /**
     * 批量添加或更新es数据，es的id值根据参数idField从list中获取
     * 比如 idField 的值为 userid
     * list的值为[{"userid":"1","name":"张三"}]
     * 则，es中的id的值为 1
     * 如果使用该接口，则list中的每条数据都必须包含 idField 参数给定的字段
     *
     * @param params 参数  包括type, idField和list
     * @return 是否成功
     */
    @PostMapping("/addOrUpdateDocument")
    public JsonResult addOrUpdateDocument(@RequestBody JSONObject params) {
        String type = params.getString("type");
        if (StringUtils.isBlank(type)) {
            return new JsonResult(ResultCode.PARAMS_ERROR, "type不能为空");
        }
        String idField = params.getString("idField");
        if (StringUtils.isBlank(idField)) {
            return new JsonResult(ResultCode.PARAMS_ERROR, "idField不能为空");
        }
        String otherStr = JSON.toJSONString(params.get("list"));
        List<Map<String, Object>> list = JSON.parseObject(otherStr, new TypeReference<List<Map<String, Object>>>() {
        });
        ESUtil.addOrUpdateDocuments(list, index, type, idField);
        return new JsonResult();
    }

    /**
     * 指定id添加es数据
     *
     * @param params 参数  包括type,id和list
     * @return 是否添加成功
     */
    @PostMapping("/addDocuments")
    public JsonResult addDocuments(@RequestBody JSONObject params) {
        String type = params.getString("type");
        if (StringUtils.isBlank(type)) {
            return new JsonResult(ResultCode.PARAMS_ERROR, "type不能为空");
        }
        String idField = params.getString("id");
        if (StringUtils.isBlank(idField)) {
            return new JsonResult(ResultCode.PARAMS_ERROR, "id不能为空");
        }
        Map<String, Object> map = (Map<String, Object>) params.get("map");
        ESUtil.addDocuments(map, index, type, idField);
        return new JsonResult();
    }

    /**
     * 根据id删除数据
     *
     * @param type es中的type
     * @param id   id
     * @return 是否删除成功
     */
    @DeleteMapping("/delDocument")
    public JsonResult delDocument(@RequestParam("type") String type, @RequestParam("id") String id) {
        if (StringUtils.isBlank(type)) {
            return new JsonResult(ResultCode.PARAMS_ERROR, "type不能为空");
        }
        if (StringUtils.isBlank(id)) {
            return new JsonResult(ResultCode.PARAMS_ERROR, "id不能为空");
        }
        ESUtil.delDocument(index, type, id);
        return new JsonResult();
    }


    @PostMapping("/updateByQuery")
    public JsonResult updateByQuery(@RequestBody UpdateByQueryDTO dto) {
        if (StringUtils.isBlank(dto.getConditionField())) {
            return new JsonResult(ResultCode.PARAMS_ERROR, "conditionField不能为空");
        }
        if (null == dto.getConditionValue()) {
            return new JsonResult(ResultCode.PARAMS_ERROR, "conditionValue不能为空");
        }
        if (StringUtils.isBlank(dto.getUpdateField())) {
            return new JsonResult(ResultCode.PARAMS_ERROR, "updateField不能为空");
        }
        if (null == dto.getUpdateValue()) {
            return new JsonResult(ResultCode.PARAMS_ERROR, "updateValue不能为空");
        }

        ESUtil.updateByQuery(index, dto);
        return new JsonResult();
    }
}
